package com.lc1993929.tank.service;

import com.lc1993929.tank.behavior.*;
import com.lc1993929.tank.constants.Action;
import com.lc1993929.tank.constants.Condition;
import com.lc1993929.tank.constants.MapElement;
import com.lc1993929.tank.constants.MapEnum;
import com.lc1993929.tank.entity.requestvo.Init;
import com.lc1993929.tank.entity.tank.Tank;
import com.lc1993929.tank.entity.vo.TankResult;
import com.lc1993929.tank.map.Coord;
import com.lc1993929.tank.map.GameMap;
import com.lc1993929.tank.util.MapUtil;
import com.lc1993929.tank.util.Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Created by LiuChang on 2018/11/26.
 */
@Service
public class GlobalService {

    @Autowired
    private Armata1Behavior armata1Behavior;
    @Autowired
    private Armata2Behavior armata2Behavior;
    @Autowired
    private T90Behavior t90Behavior;
    @Autowired
    private K2PantherBehavior k2PantherBehavior;
    @Autowired
    private WZ123Behavior wz123Behavior;

    /**
     * 初始化所有信息
     */
    public void init(Init init) {
        Condition.team = init.getTeam();
        Condition.residueGoldNum = 2;
        Condition.myGoldNum = 0;
        Condition.enemyGoldNum = 0;
        Condition.resurgenceCoords = new ArrayList<>();
        Condition.mistyCoords = new ArrayList<>();
        //初始化双方坦克
        ArrayList<Tank> myTanks;
        ArrayList<Tank> enemyTanks;
        if ("tB".equals(init.getTeam())) {
            myTanks = init.getTB().getTanks();
            enemyTanks = init.getTC().getTanks();
            myTanks.forEach(tank -> {
                if ("B1".equals(tank.tId)) {
                    Condition.myK2Panther = tank;
                } else if ("B2".equals(tank.tId)) {
                    Condition.myT90 = tank;
                } else if ("B3".equals(tank.tId)) {
                    Condition.myArmata1 = tank;
                } else if ("B4".equals(tank.tId)) {
                    Condition.myArmata2 = tank;
                } else if ("B5".equals(tank.tId)) {
                    Condition.myWZ123 = tank;
                }
            });
            enemyTanks.forEach(tank -> {
                if ("C1".equals(tank.tId)) {
                    Condition.enemyK2Panther = tank;
                } else if ("C2".equals(tank.tId)) {
                    Condition.enemyT90 = tank;
                } else if ("C3".equals(tank.tId)) {
                    Condition.enemyArmata1 = tank;
                } else if ("C4".equals(tank.tId)) {
                    Condition.enemyArmata2 = tank;
                } else if ("C5".equals(tank.tId)) {
                    Condition.enemyWZ123 = tank;
                }
            });
        } else {
            myTanks = init.getTC().getTanks();
            enemyTanks = init.getTB().getTanks();
            myTanks.forEach(tank -> {
                if ("C1".equals(tank.tId)) {
                    Condition.myK2Panther = tank;
                } else if ("C2".equals(tank.tId)) {
                    Condition.myT90 = tank;
                } else if ("C3".equals(tank.tId)) {
                    Condition.myArmata1 = tank;
                } else if ("C4".equals(tank.tId)) {
                    Condition.myArmata2 = tank;
                } else if ("C5".equals(tank.tId)) {
                    Condition.myWZ123 = tank;
                }
            });
            enemyTanks.forEach(tank -> {
                if ("B1".equals(tank.tId)) {
                    Condition.enemyK2Panther = tank;
                } else if ("B2".equals(tank.tId)) {
                    Condition.enemyT90 = tank;
                } else if ("B3".equals(tank.tId)) {
                    Condition.enemyArmata1 = tank;
                } else if ("B4".equals(tank.tId)) {
                    Condition.enemyArmata2 = tank;
                } else if ("B5".equals(tank.tId)) {
                    Condition.enemyWZ123 = tank;
                }
            });
        }
        //初始化NPC
        Condition.npc = init.getTA().getTanks().get(0);
        //初始化地图
        Integer[][] enemyValueMap = new Integer[init.getView().getColLen()][init.getView().getRowLen()];
        Integer[][] myValueMap = new Integer[init.getView().getColLen()][init.getView().getRowLen()];
        HashMap<Coord, MapElement> maps = new HashMap<>();
        ArrayList<ArrayList<MapEnum>> map = init.getView().getMap();
        MapElement mapElement = null;
        for (int y = 0; y < map.size(); y++) {
            ArrayList<MapEnum> xList = map.get(y);
            for (int x = 0; x < xList.size(); x++) {
                MapEnum mapEnum = xList.get(x);
                mapElement = Util.mapEnemToMapElement(mapEnum);
                Coord coord = new Coord(x, y);
                maps.put(coord, mapElement);
                //如果发现了坦克，设置坦克坐标
                if (mapElement == MapElement.MY_K2PANTHER) {
                    Condition.myK2Panther.coord = coord;
                } else if (mapElement == MapElement.MY_T90) {
                    Condition.myT90.coord = coord;
                } else if (mapElement == MapElement.MY_ARMATA1) {
                    Condition.myArmata1.coord = coord;
                } else if (mapElement == MapElement.MY_ARMATA2) {
                    Condition.myArmata2.coord = coord;
                } else if (mapElement == MapElement.MY_WZ123) {
                    Condition.myWZ123.coord = coord;
                } else if (mapElement == MapElement.NPC) {
                    Condition.npc.coord = coord;
                } else if (mapElement == MapElement.ENEMY_K2PANTHER) {
                    Condition.enemyK2Panther.coord = coord;
                } else if (mapElement == MapElement.ENEMY_T90) {
                    Condition.enemyT90.coord = coord;
                } else if (mapElement == MapElement.ENEMY_ARMATA1) {
                    Condition.enemyArmata1.coord = coord;
                } else if (mapElement == MapElement.ENEMY_ARMATA2) {
                    Condition.enemyArmata2.coord = coord;
                } else if (mapElement == MapElement.ENEMY_WZ123) {
                    Condition.enemyWZ123.coord = coord;
                } else if (mapElement == MapElement.RESURGENCE) {
                    Condition.resurgenceCoords.add(coord);
                } else if (mapElement == MapElement.MISTY) {
                    Condition.mistyCoords.add(coord);
                }
            }
        }
        Condition.gameMap = new GameMap(maps, enemyValueMap, myValueMap, init.getView().getColLen(), init.getView().getRowLen());
        Condition.gameMap.clearMyValueMap();
        Condition.gameMap.clearEnemyValueMap();
        Condition.gameMap.updateByAllMyTank();
        Condition.gameMap.updateByAllEnemyTank();
        //    记录集合地址
        Condition.formationCoord = Condition.myT90.coord;
        Condition.centerCoord = new Coord(Condition.gameMap.width / 2, Condition.gameMap.hight / 2);
    }

    /**
     * 做全局统一的数据更新
     */
    public void refreshAll(Init init) {
        //重置复活币和迷雾集合
        Condition.resurgenceCoords.clear();
        Condition.mistyCoords.clear();
        //刷新双方坦克数据
        ArrayList<Tank> myTanks;
        ArrayList<Tank> enemyTanks;
        if ("tB".equals(init.getTeam())) {
            Condition.myExtend = init.getTB().getExtend();
            Condition.enemyExtend = init.getTC().getExtend();
            //复活币
            Integer myGoldNum = init.getTB().getGlod();
            if (myGoldNum > Condition.myGoldNum) {
                Condition.residueGoldNum = Condition.residueGoldNum - (myGoldNum - Condition.myGoldNum);
                Condition.myGoldNum = myGoldNum;
            }
            Integer enemyGoldNum = init.getTC().getGlod();
            if (enemyGoldNum > Condition.enemyGoldNum) {
                Condition.residueGoldNum = Condition.residueGoldNum - (enemyGoldNum - Condition.enemyGoldNum);
                Condition.enemyGoldNum = enemyGoldNum;
            }
            myTanks = init.getTB().getTanks();
            enemyTanks = init.getTC().getTanks();
            myTanks.forEach(tank -> {
                if ("B1".equals(tank.tId)) {
                    refreshMyTank(Condition.myK2Panther, tank);
                } else if ("B2".equals(tank.tId)) {
                    refreshMyTank(Condition.myT90, tank);
                } else if ("B3".equals(tank.tId)) {
                    refreshMyTank(Condition.myArmata1, tank);
                } else if ("B4".equals(tank.tId)) {
                    refreshMyTank(Condition.myArmata2, tank);
                } else if ("B5".equals(tank.tId)) {
                    refreshMyTank(Condition.myWZ123, tank);
                }
            });
            enemyTanks.forEach(tank -> {
                if ("C1".equals(tank.tId)) {
                    refreshEnemyTank(Condition.enemyK2Panther, tank);
                } else if ("C2".equals(tank.tId)) {
                    refreshEnemyTank(Condition.enemyT90, tank);
                } else if ("C3".equals(tank.tId)) {
                    refreshEnemyTank(Condition.enemyArmata1, tank);
                } else if ("C4".equals(tank.tId)) {
                    refreshEnemyTank(Condition.enemyArmata2, tank);
                } else if ("C5".equals(tank.tId)) {
                    refreshEnemyTank(Condition.enemyWZ123, tank);
                }
            });
        } else {
            Condition.myExtend = init.getTC().getExtend();
            Condition.enemyExtend = init.getTB().getExtend();
            //复活币
            Integer myGoldNum = init.getTC().getGlod();
            if (myGoldNum > Condition.myGoldNum) {
                Condition.residueGoldNum = Condition.residueGoldNum - (myGoldNum - Condition.myGoldNum);
                Condition.myGoldNum = myGoldNum;
            }
            Integer enemyGoldNum = init.getTB().getGlod();
            if (enemyGoldNum > Condition.enemyGoldNum) {
                Condition.residueGoldNum = Condition.residueGoldNum - (enemyGoldNum - Condition.enemyGoldNum);
                Condition.enemyGoldNum = enemyGoldNum;
            }
            myTanks = init.getTC().getTanks();
            enemyTanks = init.getTB().getTanks();
            myTanks.forEach(tank -> {
                if ("C1".equals(tank.tId)) {
                    refreshMyTank(Condition.myK2Panther, tank);
                } else if ("C2".equals(tank.tId)) {
                    refreshMyTank(Condition.myT90, tank);
                } else if ("C3".equals(tank.tId)) {
                    refreshMyTank(Condition.myArmata1, tank);
                } else if ("C4".equals(tank.tId)) {
                    refreshMyTank(Condition.myArmata2, tank);
                } else if ("C5".equals(tank.tId)) {
                    refreshMyTank(Condition.myWZ123, tank);
                }
            });
            enemyTanks.forEach(tank -> {
                if ("B1".equals(tank.tId)) {
                    refreshEnemyTank(Condition.enemyK2Panther, tank);
                } else if ("B2".equals(tank.tId)) {
                    refreshEnemyTank(Condition.enemyT90, tank);
                } else if ("B3".equals(tank.tId)) {
                    refreshEnemyTank(Condition.enemyArmata1, tank);
                } else if ("B4".equals(tank.tId)) {
                    refreshEnemyTank(Condition.enemyArmata2, tank);
                } else if ("B5".equals(tank.tId)) {
                    refreshEnemyTank(Condition.enemyWZ123, tank);
                }
            });
        }
        Condition.npc = init.getTA().getTanks().get(0);
        //初始化地图
        HashMap<Coord, MapElement> maps = new HashMap<>();
        ArrayList<ArrayList<MapEnum>> map = init.getView().getMap();
        MapElement mapElement = null;
        for (int y = 0; y < map.size(); y++) {
            ArrayList<MapEnum> xList = map.get(y);
            for (int x = 0; x < xList.size(); x++) {
                MapEnum mapEnum = xList.get(x);
                mapElement = Util.mapEnemToMapElement(mapEnum);
                Coord coord = new Coord(x, y);
                maps.put(coord, mapElement);
                //如果发现了坦克，设置坦克坐标
                if (mapElement == MapElement.MY_K2PANTHER) {
                    Condition.myK2Panther.coord = coord;
                    Condition.myK2Panther.oldCoord = new Coord(coord.x, coord.y);
                } else if (mapElement == MapElement.MY_T90) {
                    Condition.myT90.coord = coord;
                    Condition.myT90.oldCoord = new Coord(coord.x, coord.y);
                } else if (mapElement == MapElement.MY_ARMATA1) {
                    Condition.myArmata1.coord = coord;
                    Condition.myArmata1.oldCoord = new Coord(coord.x, coord.y);
                } else if (mapElement == MapElement.MY_ARMATA2) {
                    Condition.myArmata2.coord = coord;
                    Condition.myArmata2.oldCoord = new Coord(coord.x, coord.y);
                } else if (mapElement == MapElement.MY_WZ123) {
                    Condition.myWZ123.coord = coord;
                    Condition.myWZ123.oldCoord = new Coord(coord.x, coord.y);
                } else if (mapElement == MapElement.NPC) {
                    Condition.npc.coord = coord;
                } else if (mapElement == MapElement.ENEMY_K2PANTHER) {
                    Condition.enemyK2Panther.coord = coord;
                    Condition.enemyK2Panther.oldCoord = new Coord(coord.x, coord.y);
                } else if (mapElement == MapElement.ENEMY_T90) {
                    Condition.enemyT90.coord = coord;
                    Condition.enemyT90.oldCoord = new Coord(coord.x, coord.y);
                } else if (mapElement == MapElement.ENEMY_ARMATA1) {
                    Condition.enemyArmata1.coord = coord;
                    Condition.enemyArmata1.oldCoord = new Coord(coord.x, coord.y);
                } else if (mapElement == MapElement.ENEMY_ARMATA2) {
                    Condition.enemyArmata2.coord = coord;
                    Condition.enemyArmata2.oldCoord = new Coord(coord.x, coord.y);
                } else if (mapElement == MapElement.ENEMY_WZ123) {
                    Condition.enemyWZ123.coord = coord;
                    Condition.enemyWZ123.oldCoord = new Coord(coord.x, coord.y);
                } else if (mapElement == MapElement.RESURGENCE) {
                    Condition.resurgenceCoords.add(coord);
                } else if (mapElement == MapElement.MISTY) {
                    Condition.mistyCoords.add(coord);
                }
            }
        }
        Condition.gameMap = new GameMap(maps, Condition.gameMap.enemyValueMap, Condition.gameMap.myValueMap, init.getView().getColLen(), init.getView().getRowLen());
        Condition.gameMap.clearEnemyValueMap();
        Condition.gameMap.clearMyValueMap();
        Condition.gameMap.updateByAllMyTank();
        Condition.gameMap.updateByAllEnemyTank();
        //    刷新是否集火NPC
        Condition.assistedNPC = false;
        MapUtil.refreshAssistedNPC();
    }

    public List<TankResult> doAction() {
        List<TankResult> tankResults = new ArrayList<>();
        //优先进行99式的动作
        try {
            if (Condition.myWZ123.shengyushengming > 0) {
                Action wz123Action = wz123Behavior.behavior();
                tankResults.add(Util.actionToResult(wz123Action, Condition.myWZ123.tId));
            }
        } catch (Exception e) {
            e.printStackTrace();
            TankResult.Type randomResultType = Util.getRandomResultType();
            TankResult.TankResultBuilder tankResultBuilder = TankResult.builder().tId(Condition.myWZ123.tId).direction(Util.getRandomDirection()).type(randomResultType).useGlod(false);
            if (randomResultType == TankResult.Type.MOVE) {
                tankResultBuilder.length(1);
            } else {
                tankResultBuilder.length(3);
            }
            tankResults.add(tankResultBuilder.build());
        }
        try {
            if (Condition.myK2Panther.shengyushengming > 0) {
                Action k2PantherAction = k2PantherBehavior.behavior();
                tankResults.add(Util.actionToResult(k2PantherAction, Condition.myK2Panther.tId));
            } else if (Condition.myGoldNum > 0) {
                Action k2PantherAction = k2PantherBehavior.behavior();
                k2PantherAction.setUseGlod(true);
                tankResults.add(Util.actionToResult(k2PantherAction, Condition.myK2Panther.tId));
            }
        } catch (Exception e) {
            e.printStackTrace();
            TankResult.Type randomResultType = Util.getRandomResultType();
            TankResult.TankResultBuilder tankResultBuilder = TankResult.builder().tId(Condition.myK2Panther.tId).direction(Util.getRandomDirection()).type(randomResultType).length(1).useGlod(false);
            tankResults.add(tankResultBuilder.build());
        }
        try {
            if (Condition.myT90.shengyushengming > 0) {
                Action t90Action = t90Behavior.behavior();
                tankResults.add(Util.actionToResult(t90Action, Condition.myT90.tId));
            } else if (Condition.myGoldNum > 0) {
                Action t90Action = t90Behavior.behavior();
                t90Action.setUseGlod(true);
                tankResults.add(Util.actionToResult(t90Action, Condition.myT90.tId));
            }
        } catch (Exception e) {
            e.printStackTrace();
            TankResult.Type randomResultType = Util.getRandomResultType();
            TankResult.TankResultBuilder tankResultBuilder = TankResult.builder().tId(Condition.myT90.tId).direction(Util.getRandomDirection()).type(randomResultType).length(1).useGlod(false);
            tankResults.add(tankResultBuilder.build());
        }
        try {
            if (Condition.myArmata1.shengyushengming > 0) {
                Action armata1Acion = armata1Behavior.behavior();
                tankResults.add(Util.actionToResult(armata1Acion, Condition.myArmata1.tId));
            }
        } catch (Exception e) {
            e.printStackTrace();
            TankResult.Type randomResultType = Util.getRandomResultType();
            TankResult.TankResultBuilder tankResultBuilder = TankResult.builder().tId(Condition.myArmata1.tId).direction(Util.getRandomDirection()).type(randomResultType).useGlod(false);
            if (randomResultType == TankResult.Type.MOVE) {
                tankResultBuilder.length(2);
            } else {
                tankResultBuilder.length(1);
            }
            tankResults.add(tankResultBuilder.build());
        }
        try {
            if (Condition.myArmata2.shengyushengming > 0) {
                Action armata2Action = armata2Behavior.behavior();
                tankResults.add(Util.actionToResult(armata2Action, Condition.myArmata2.tId));
            }
        } catch (Exception e) {
            e.printStackTrace();
            TankResult.Type randomResultType = Util.getRandomResultType();
            TankResult.TankResultBuilder tankResultBuilder = TankResult.builder().tId(Condition.myArmata2.tId).direction(Util.getRandomDirection()).type(randomResultType).useGlod(false);
            if (randomResultType == TankResult.Type.MOVE) {
                tankResultBuilder.length(2);
            } else {
                tankResultBuilder.length(1);
            }
            tankResults.add(tankResultBuilder.build());
        }


        //判断是否是最后时间并使用复活币
        if (Condition.useGoldLastTime && Condition.myGoldNum > 0) {
            //找出复活后整体血量增加最多的坦克
            Tank tank = MapUtil.findBestResurgenceTank();
            if (tank != null) {
                if (tank.shengyushengming <= 0) {
                    if (tank.tId.equals(Condition.myArmata1.tId)) {
                        TankResult armata1Result = Util.actionToResult(armata1Behavior.behavior(), tank.tId);
                        armata1Result.setUseGlod(true);
                        tankResults.add(armata1Result);
                    } else if (tank.tId.equals(Condition.myArmata2.tId)) {
                        TankResult armata2Result = Util.actionToResult(armata2Behavior.behavior(), tank.tId);
                        armata2Result.setUseGlod(true);
                        tankResults.add(armata2Result);
                    } else if (tank.tId.equals(Condition.myT90.tId)) {
                        TankResult t90Result = Util.actionToResult(t90Behavior.behavior(), tank.tId);
                        t90Result.setUseGlod(true);
                        tankResults.add(t90Result);
                    } else if (tank.tId.equals(Condition.myK2Panther.tId)) {
                        TankResult k2PantherResult = Util.actionToResult(k2PantherBehavior.behavior(), tank.tId);
                        k2PantherResult.setUseGlod(true);
                        tankResults.add(k2PantherResult);
                    } else {
                        TankResult wz123Result = Util.actionToResult(wz123Behavior.behavior(), tank.tId);
                        wz123Result.setUseGlod(true);
                        tankResults.add(wz123Result);
                    }
                } else {
                    tankResults = tankResults.stream().peek(tankResult -> {
                        if (tankResult.gettId().equals(tank.tId)) {
                            tankResult.setUseGlod(true);
                        }
                    }).collect(Collectors.toList());
                }
            }
        }
        return tankResults;
    }


    private void refreshMyTank(Tank old, Tank news) {
        old.tId = news.tId;
        old.name = news.name;
        old.gongji = news.gongji;
        old.shengming = news.shengming;
        old.isBeAttacked = news.shengyushengming < old.shengyushengming;
        old.shengyushengming = news.shengyushengming;
        old.yidong = news.yidong;
        old.shecheng = news.shecheng;
        old.shiye = news.shiye;
        old.mingzhong = news.mingzhong;
        old.direction = news.direction;
        old.action = null;
        if (news.shengyushengming > 0 || Condition.myGoldNum == 0) {
            old.coord = null;
        }
    }

    private void refreshEnemyTank(Tank old, Tank news) {
        old.tId = news.tId;
        old.name = news.name;
        old.gongji = news.gongji;
        old.shengming = news.shengming;
        old.shengyushengming = news.shengyushengming;
        old.yidong = news.yidong;
        old.shecheng = news.shecheng;
        old.shiye = news.shiye;
        old.mingzhong = news.mingzhong;
        old.direction = news.direction;
        old.coord = null;
    }

    public void startCountDown() {
        if (Condition.lastTimeThread != null && !Condition.lastTimeThread.isInterrupted()) {
            //如果已有计时线程则打断计时线程
            Condition.lastTimeThread.interrupt();
        }
        //将最后时刻标志位至为false
        Condition.useGoldLastTime = false;
        Thread lastTimeThread = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(280);
                Condition.useGoldLastTime = true;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        Condition.lastTimeThread = lastTimeThread;
        lastTimeThread.start();
    }
}
